package wsserver

import (
	"errors"
	"fmt"
	"git.supremind.info/product/box/vehicle/common"
	"github.com/gin-gonic/gin"
	"github.com/gorilla/websocket"
	"net/http"
	"sync"
	"time"
)

type Connection struct {
	wsConn *websocket.Conn
	//读取websocket的channel
	inChan chan []byte
	//给websocket写消息的channel
	outChan   chan []byte
	closeChan chan byte
	mutex     sync.Mutex
	//closeChan 状态
	isClosed bool
}

//初始化upgrader实例，用于升级请求为websocket请求
var wsUpgrader = websocket.Upgrader{
	ReadBufferSize:  4096,
	WriteBufferSize: 1024,
	CheckOrigin: func(r *http.Request) bool {
		if r.Method != "GET" {
			fmt.Println("method is not GET")
			return false
		}
		return true
	},
}

var ModelWsUpgradeConn = make(map[int64]*Connection)
var ModelStatusWsUpgradeConn = make(map[int64]*Connection)

// 广播消息
func SendModelMessage(typeStr string, msg []byte) {
	if typeStr == "model" {
		for _, conn := range ModelWsUpgradeConn {
			conn.outChan <- msg
		}
	}
	if typeStr == "model_status" {
		for _, conn := range ModelStatusWsUpgradeConn {
			conn.outChan <- msg
		}
	}
}

//测试websocket链接方法
func WsPing(c *gin.Context) {
	typeMode := c.Query("type")
	upgrade, err := wsUpgrader.Upgrade(c.Writer, c.Request, nil)
	if err != nil {
		return
	}

	connection, conErr := InitConnection(upgrade)
	if conErr == nil {
		common.Logger.Info("初始化websocket成功")
		if typeMode == "model" {
			ModelWsUpgradeConn[time.Now().Unix()] = connection
		} else if typeMode == "model_status" {
			ModelStatusWsUpgradeConn[time.Now().Unix()] = connection
		} else {
			connection.Close()
		}
	}

	//upgrade.SetCloseHandler(func(code int, text string) error {
	//	common.Logger.Infof("链接断开, code:%d", code)
	//	upgrade.Close()
	//	return nil
	//})

	//if typeMode == "model" {
	//	ModelWsUpgradeConn[time.Now().Unix()] = upgrade
	//} else if typeMode == "model_status" {
	//	ModelStatusWsUpgradeConn[time.Now().Unix()] = upgrade
	//} else {
	//	upgrade.Close()
	//}

	//go func() {
	//	_, _, _ = upgrade.ReadMessage()
	//}()

	//if typeMode == "model" {
	//	for {
	//		//websocket发送数据
	//		marshal, err := json.Marshal("哈哈哈")
	//		if err != nil {
	//			break
	//		}
	//		//err = upgrade.WriteMessage(message, p)
	//		err = upgrade.WriteJSON(string(marshal))
	//		if err != nil {
	//			break
	//		}
	//		time.Sleep(1e9)
	//	}
	//}
	//
	//if typeMode == "model_status" {
	//	for {
	//		//websocket发送数据
	//		marshal, err := json.Marshal("呵呵呵")
	//		if err != nil {
	//			break
	//		}
	//		//err = upgrade.WriteMessage(message, p)
	//		err = upgrade.WriteJSON(string(marshal))
	//		if err != nil {
	//			break
	//		}
	//		time.Sleep(1e9)
	//	}
	//}
	//go func() {
	//	defer upgrade.Close()
	//	for {
	//		//websocket发送数据
	//		_, _, err2 := upgrade.ReadMessage()
	//		if err2 != nil {
	//			common.Logger.Infof("websocket ping link error %v", err2)
	//			break
	//		}
	//		time.Sleep(2e9)
	//	}
	//}()
}

//初始化长连接
func InitConnection(wsConn *websocket.Conn) (conn *Connection, err error) {
	conn = &Connection{
		wsConn:    wsConn,
		inChan:    make(chan []byte, 1000),
		outChan:   make(chan []byte, 1000),
		closeChan: make(chan byte, 1),
	}
	//启动读协程
	go conn.readLoop()
	//启动写协程
	go conn.writeLoop()
	return
}

//读取websocket消息
func (conn *Connection) ReadMessage() (data []byte, err error) {
	select {
	case data = <-conn.inChan:
	case <-conn.closeChan:
		err = errors.New("connection is closed")
	}
	return
}

//发送消息到websocket
func (conn *Connection) WriteMessage(data []byte) (err error) {
	select {
	case conn.outChan <- data:
	case <-conn.closeChan:
		err = errors.New("connection is closed")
	}
	return
}

//关闭连接
func (conn *Connection) Close() {
	//线程安全的Close,可重入
	conn.wsConn.Close()

	//只执行一次
	conn.mutex.Lock()
	if !conn.isClosed {
		close(conn.closeChan)
		conn.isClosed = true
	}
	conn.mutex.Unlock()
}

func (conn *Connection) readLoop() {
	var (
		data []byte
		err  error
	)
	for {
		if _, data, err = conn.wsConn.ReadMessage(); err != nil {
			goto ERR
		}
		common.Logger.Infof("读取到的值：%s", string(data))
		//如果数据量过大阻塞在这里,等待inChan有空闲的位置！
		select {
		case conn.inChan <- data:
		case <-conn.closeChan:
			//closeChan关闭的时候
			goto ERR
		}
	}
ERR:
	conn.Close()
}

func (conn *Connection) writeLoop() {
	var (
		data []byte
		err  error
	)
	for {
		select {
		case data = <-conn.outChan:
		case <-conn.closeChan:
			goto ERR
		}
		if err = conn.wsConn.WriteMessage(websocket.TextMessage, data); err != nil {
			goto ERR
		}
	}
ERR:
	conn.Close()
}

func RemoveModelStatusSocketMapLoop() {
	for true {
		for i, connection := range ModelStatusWsUpgradeConn {
			if connection.isClosed {
				delete(ModelStatusWsUpgradeConn, i)
			}
		}
		time.Sleep(1e9)
	}
}

func RemoveModelSocketMapLoop() {
	for true {
		for i, connection := range ModelWsUpgradeConn {
			if connection.isClosed {
				delete(ModelWsUpgradeConn, i)
			}
		}
		time.Sleep(1e9)
	}
}
